﻿//Copyright (c) 2010 William Liu, Enoch Ye
//William Liu <william.lyz@gmail.com>
//Enoch Ye <moonlight.enoch@gmail.com>

//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at

//       http://www.apache.org/licenses/LICENSE-2.0

//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Specialized;

namespace GBG_DBM.Support.BLL
{
    class ConfOperator
    {
        /// <summary>
        /// This class is using to write .ini file,
        /// which is application configuration file
        /// Temporary abort this class, decide to write the setting inside the code
        /// </summary>
        /// 
        //use system method to read/write *.ini file
        [DllImport ("kernel32")]
        private static extern bool WritePrivateProfileString (string section, string key, string val, string filePath);
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString (string section, string key, string def, byte[] retVal, int size, string filePath);

        #region FILEDS

        private string _fileName;
        //private string _backupPath;

        #endregion

        #region PROPERTIES

        //public string BackupPath { get { return _backupPath; } }
        public string ConfFileInfo { get { return _fileName; } }

        #endregion

        #region CONSTRUCTORS

        public ConfOperator(string FileName)
        {
            FileInfo _fileInfo = new FileInfo(FileName);
            if ((!_fileInfo.Exists))
            {
                StreamWriter _streamWriter = new StreamWriter(FileName, false, Encoding.UTF8);
                try
                {
                    _streamWriter.Write("Application Configuration");
                    _streamWriter.Close();
                }
                catch
                {
                    throw (new ApplicationException("Application Configuration file does not exist"));
                }
            }
            FileName = _fileInfo.FullName;
        }

        #endregion

        #region METHODS

        //write ini file
        public void WriteString(string Section, string KeyWord, string Value)
        {
            if (!WritePrivateProfileString(Section, KeyWord, Value, _fileName))
            {
                throw (new ApplicationException("An error occurred writing the configuration file. The file cannot be saved"));
            }
        }

        //read ini file (specified fields)
        public string ReadString(string Section, string KeyWord, string Default)
        {
            Byte[] _buffer = new Byte[65535];
            int _bufLength = GetPrivateProfileString(Section, KeyWord, Default, _buffer, _buffer.GetUpperBound(0), _fileName);
            string _string = Encoding.GetEncoding("UTF8").GetString(_buffer);
            _string = _string.Substring(0, _bufLength);
            return _string.Trim();
        }

        //read integers
        public int ReadIntegers(string Section, string KeyWord, int Default)
        {
            string _intStr = ReadString(Section, KeyWord, Convert.ToString(Default));
            try
            {
                return Convert.ToInt32(_intStr);
            }
            catch (Exception _ex)
            {
                throw new Exception(_ex.Message);
                //return Default;
            }
        }

        //Write integers
        public void WriteInteger(string Section, string KeyWord, int Value)
        {
            WriteString(Section, KeyWord, Value.ToString());
        }

        //Read Bool
        public bool ReadBool(string Section, string KeyWord, bool Default)
        {
            try
            {
                return Convert.ToBoolean(ReadString(Section, KeyWord, Convert.ToString(Default)));
            }
            catch (Exception _ex)
            {
                throw new Exception(_ex.Message);
                //return Default;
            }
        }

        //Write Bool
        public void WriteBool(string Section, string KeyWord, bool Value)
        {
            WriteString(Section, KeyWord, Convert.ToString(Value));
        }

        //从Ini文件中，将指定的Section名称中的所有Ident添加到列表中
        //Add all the Keyword that from a specific Section to a list
        public void ReadSection(string Section, StringCollection KeyWord)
        {
            Byte[] _buffer = new Byte[16384];
            //KeyWord.Clear();

            int _bufLength = GetPrivateProfileString(Section, null, null, _buffer, _buffer.GetUpperBound(0), _fileName);
            //对Section进行解析
            //conver buff to string
            GetStringsFromBuffer(_buffer, _bufLength, KeyWord);
        }

        private void GetStringsFromBuffer(Byte[] Buffer, int bufLength, StringCollection Strings)
        {
            Strings.Clear();
            if (bufLength != 0)
            {
                int start = 0;
                for (int i = 0; i < bufLength; i++)
                {
                    if ((Buffer[i] == 0) && ((i - start) > 0))
                    {
                        String _string = Encoding.GetEncoding("UTF8").GetString(Buffer, start, i - start);
                        Strings.Add(_string);
                        start = i + 1;
                    }
                }
            }
        }

        //从Ini文件中，读取所有的Sections的名称
        //read all the Sections from *.ini file
        public void ReadSections(StringCollection SectionList)
        {
            //Note: 必须得用Bytes来实现, StringBuilder只能取到第一个Section
            //Have to use Byte, StringBuilder only can read first Section
            byte[] _buffer = new byte[65535];
            int _bufLength = 0;
            _bufLength = GetPrivateProfileString(null, null, null, _buffer, _buffer.GetUpperBound(0), _fileName);
            GetStringsFromBuffer(_buffer, _bufLength, SectionList);
        }
　　　　
        //读取指定的Section的所有Value到列表中
        //read all the Values from specific Section
        public void ReadSectionValues(string Section, NameValueCollection Values)
        {
            StringCollection _keyList = new StringCollection();
            ReadSection(Section, _keyList);
            Values.Clear();
            foreach (string _key in _keyList)
            {
                Values.Add(_key, ReadString(Section, _key, ""));
            }
        }

        //清除某个Section
        //Clean/delete specific Section
        public void EraseSection(string Section)
        {
            if (!WritePrivateProfileString(Section, null, null, _fileName))
            {
                throw (new ApplicationException("An error occurred cleaning specific Section"));
            }
        }
　　　　
        //删除某个Section下的键
        //delete specific key from specific Section
        public void DeleteKey(string Section, string Ident)
        {
            WritePrivateProfileString(Section, Ident, null, _fileName);
        }

        //检查某个Section下的某个键值是否存在
        //check keys in specific Section
        public bool ValueExists(string Section, string KeyWord)
        {
            StringCollection _keyWord = new StringCollection();
            ReadSection(Section, _keyWord);
            return _keyWord.IndexOf(KeyWord) > -1;
        }

        //Note:对于Win9X，来说需要实现UpdateFile方法将缓冲中的数据写入文件
        //在Win NT, 2000和XP上，都是直接写文件，没有缓冲，所以，无须实现UpdateFile
        //执行完对Ini文件的修改之后，应该调用本方法更新缓冲区。
        //This method only for Win9X
        //public void UpdateFile()
        //{
        //    WritePrivateProfileString(null, null, null, _fileName);
        //}

        ////确保资源的释放
        ////release resource
        //~ConfOperator()
        //{
        //    UpdateFile();
        //}

        #endregion

    }
}
